//*****************************************************************************
// JFab (http://code.google.com/p/jfab)
// Copyright (c) 2011-2012 JFab.org
// Admin jfab@jeffreythompson.net
//
// See the file "LICENSE.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//*****************************************************************************

package org.jfab.swingui;

import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import org.apache.commons.lang3.Validate;
import org.jfab.swingui.decorator.Decorator;
import org.jfab.swingui.editpane.EditPane;

/**
 * Provides an edit pane for JFab.
 */
public class EditPanel extends JPanel
{
    /** Serial version UID. */
    private static final long serialVersionUID = 1L;

    /** Action manager. */
    private final ActionManager _actionManager;

    /** Button panel. */
    private final JPanel _buttonPanel;

    /** Data listeners. */
    private List<PropertyChangeListener> _dataListeners = new ArrayList<PropertyChangeListener>();

    /** Edit pane. */
    private EditPane<?> _editPane;

    /** Main panel. */
    private JPanel _mainPanel = new JPanel();

    /**
     * Construct this object with the given parameter.
     * 
     * @param actionManager Action manager. (required)
     */
    public EditPanel(final ActionManager actionManager)
    {
        Validate.notNull(actionManager, "actionManager is null");

        _actionManager = actionManager;

        _buttonPanel = createButtonPanel();
        final JScrollPane scrollPane = new JScrollPane(_mainPanel);

        setLayout(new BorderLayout());

        add(_buttonPanel, BorderLayout.NORTH);
        add(scrollPane, BorderLayout.CENTER);

        _dataListeners.add(new PropertyChangeListener()
        {
            @Override
            public void propertyChange(final PropertyChangeEvent event)
            {
                checkActions();
            }
        });

        checkActions();
    }

    /**
     * Apply changes to the data object.
     */
    public void applyChanges()
    {
        if (_editPane != null)
        {
            _editPane.applyChanges();
        }
    }

    /**
     * @return true if the data has been changed.
     */
    public boolean isDirty()
    {
        return (_editPane != null) && _editPane.isDirty();
    }

    /**
     * @param decorator Decorator.
     */
    public void setDecorator(final Decorator<?> decorator)
    {
        EditPane<?> editPane = null;

        if (decorator != null)
        {
            editPane = decorator.getEditPane();
        }

        setEditPane(editPane);

        revalidate();
        repaint();
    }

    /**
     * @param editPane the editPane to set
     */
    public void setEditPane(final EditPane<?> editPane)
    {
        if (_editPane != null)
        {
            // Tear down the old edit pane.
            removeDataListeners(_editPane);
            _mainPanel.remove((JComponent)_editPane);
        }

        _editPane = editPane;

        if (_editPane != null)
        {
            // Set up the new edit pane.
            _mainPanel.add((JComponent)_editPane);
            addDataListeners(_editPane);

            _mainPanel.revalidate();
            revalidate();
        }

        checkActions();
    }

    /**
     * Check the enabled state of actions.
     */
    void checkActions()
    {
        _actionManager.getSaveCgObjectAction().setEnabled(isDirty());
    }

    /**
     * @param editPane the editPane to set
     */
    private void addDataListeners(final EditPane<?> editPane)
    {
        for (final PropertyChangeListener listener : _dataListeners)
        {
            editPane.addDataListener(listener);
        }
    }

    /**
     * @return a new button panel.
     */
    private JPanel createButtonPanel()
    {
        final JButton addButton = new JButton(
                _actionManager.getSaveCgObjectAction());

        final JPanel panel = new JPanel();

        panel.add(addButton);

        final JPanel answer = new JPanel();

        answer.add(panel);

        return answer;
    }

    /**
     * @param editPane the editPane to set
     */
    private void removeDataListeners(final EditPane<?> editPane)
    {
        for (final PropertyChangeListener listener : _dataListeners)
        {
            editPane.removeDataListener(listener);
        }
    }
}
